package com.sk.ccflower.lib.commonUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;

public class ObjectUtil
{
	/**
	 * Object의 내용을 String에 넣어 리턴. 멤버변수간의 분리자는 '\t'이다.
	 */
	public static String toString(Object obj)
	{
		return ObjectUtil.toString(obj, "\t");
	}

	/**
	 * Object의 내용을 String에 넣어 리턴. 멤버변수간의 분리자는 seq에 넣는다.
	 */
	public static String toString(Object obj, String sep)
	{
		StringBuffer sb = new StringBuffer();

		try
		{
			Class<?> cls = obj.getClass();
			Field[] fields = cls.getFields();

			for(int i=0; i<fields.length; i++)
			{
				sb.append(fields[i].getName()).append( "=[" ).append(fields[i].get(obj)).append("]" + sep);
			}
		} catch (Exception ex) {
		}

		return sb.toString();
	}
	
	public static void setNull(Object obj)
	{
		Field[] fields = obj.getClass().getFields();

		for(int i=0; i<fields.length; i++) {
			try {
				fields[i].set(obj, null);
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			} catch (Exception e) {
			}
		}
	}

	/**
	 * 서로 다른 타입의 Object간에 필드명과 데이터 타입이 같은 항목을 복사 기능을 제공하는 함수
	 * value를 설정한 테이터 타입은 값의 복사가 이루어진다. ( int , long, String 등 ) - 레퍼런스타입 중 유일하다.(String)
	 * 레퍼런스타입의 멤버는 주소값이 복사된다. 따라서 복사가 되어도 동일한 주소값을 지닌다.
	 * @param objTarget: 복사 대상 Object. 할당된 Object이어야 한다. null 허용하지 않음.
	 * @param objSource: 복사할 Object
	 * @param caseSensitive: 필드명의 대소문자 비교 여부, true:대소문자비교/false:대소문자무시
	 * @throws Exception
	 */
	public static void objectCopy(Object objTarget, Object objSource, boolean caseSensitive) throws Exception
	{
		Field[] fieldSource = objSource.getClass().getFields();
		Field[] fieldTarget = objTarget.getClass().getFields();

		for(int iS=0; iS<fieldSource.length; iS++)
		{
			for(int iT=0; iT<fieldTarget.length; iT++)
			{
				//fieldSource[iS].gettgetType()
				if(fieldSource[iS].getType()!=fieldTarget[iT].getType()) continue;

				if((caseSensitive && fieldTarget[iT].getName().equals(fieldSource[iS].getName()))
				|| (!caseSensitive && fieldTarget[iT].getName().toLowerCase().equals(fieldSource[iS].getName().toLowerCase())))
				{

					fieldTarget[iT].set(objTarget, fieldSource[iS].get(objSource));

					break;
				}
			}
		}
	}

	/**
	 * 서로 다른 타입의 Object간에 필드명과 데이터 타입이 같은 항목을 복사하는 기능을 제공하는 함수.
	 * Target class타입으로 생성한 Object에 데이터를 복사하여 return한다.
	 * @param clsTarget 복사대상의 class타입
	 * @param objSource 복사할 Object
	 * @param caseSensitive 필드명의 대소문자 비교 여부, true:대소문자비교/false:대소문자무시
	 * @return 복사하여 새로 생성한 target class타입의 Object
	 * @throws Exception
	 */
	public static Object objectCopy(Class<?> clsTarget, Object objSource, boolean caseSensitive) throws Exception
	{
		Object obj = clsTarget.newInstance();

		ObjectUtil.objectCopy(obj, objSource, caseSensitive);

		return obj;
	}

	/**
	 * 서로 다른 타입의 Object간에 필드명과 데이터 타입이 같은 항목을 복사하는 기능을 제공하는 함수.
	 * 입력되는 리스트 만큼의 Target타입 Object리스트를 만들어 데이터를 복사하여 return한다.
	 * @param clsTarget 복사대상의 class타입
	 * @param objSource 복사할 Object 리스트
	 * @param caseSensitive 필드명의 대소문자 비교 여부, true:대소문자비교/false:대소문자무시
	 * @return 복사하여 새로 생성한 target class타입의 Object List
	 * @throws Exception
	 */
	public static ArrayList<Object> objectCopy(Class<?> clsTarget, ArrayList<Object> arrSource, boolean caseSensitive) throws Exception
	{
		Field[] fieldTarget = clsTarget.getFields();
		Field[] fieldSource = arrSource.get(0).getClass().getFields();

		int fieldNo = 0;

		Field[] fieldCopyTarget = new Field[fieldTarget.length];
		Field[] fieldCopySource = new Field[fieldTarget.length];

		for(int iT=0; iT<fieldTarget.length; iT++)
		{
			for(int iS=0; iS<fieldSource.length; iS++)
			{
				if(fieldSource[iS].getType()!=fieldTarget[iT].getType()) continue;

				if((caseSensitive && fieldTarget[iT].getName().equals(fieldSource[iS].getName()))
				|| (!caseSensitive && fieldTarget[iT].getName().toLowerCase().equals(fieldSource[iS].getName().toLowerCase())))
				{
					fieldCopySource[fieldNo] = fieldSource[iS];
					fieldCopyTarget[fieldNo] = fieldTarget[iT];
					fieldNo ++;
					break;
				}
			}
		}

		Object obj = null;
		int size = arrSource.size();
		ArrayList<Object> arrTarget = new ArrayList<Object>(size);

		for(int i=0; i<size; i++)
		{
			obj = clsTarget.newInstance();
			arrTarget.add(obj);

			for(int j=0; j<fieldNo; j++) fieldCopyTarget[j].set(obj, fieldCopySource[j].get(arrSource.get(i)));
		}

		return arrTarget;
	}

	public static void main(String[] args){
		Source s = new Source();
		s.a1 = 10;
		s.list = new ArrayList<String>();
		s.list.add("a");
		s.str="ppp";
		Dest d = new Dest();

		try{
			ObjectUtil.objectCopy( d , s , true );
			//for( int i = 0 ; i <
			System.out.println(d.a1 + "" + (String)d.list.get(0));
			d.str = "oo";
		} catch( Exception ex ){

		}
	}
}


class Source{
	public int a1;
	public String str;
	public ArrayList<String> list;
}

class Dest{
	public int a1;
	public String str;
	public ArrayList<?> list;
}
